package com.example.cherrytest.learn.lock.sync;

import org.openjdk.jol.info.ClassLayout;

/**
 * synchronized锁升级原理演示
 */
public class SynLockUpgradeDemon {

    /**
     * 在mark-word锁类型：无锁，偏向锁，轻量锁，重量锁，以及 GC标记，
     * <p>
     * 无锁：001
     * 偏向锁：101
     * 轻量锁：00
     * 重量锁：10
     * gc标记：11
     *
     * @param args
     */
    public static void main(String[] args) {


//        nonLock();// 001
//        deviationLock();// 101
//        lightweightLock(); // 00

        weightLock(); // 10
    }

    /**
     * 重量级锁 10
     */
    private static void weightLock() {
        Object object = new Object();
        // 锁竞争
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object) {
                    System.err.println("重量锁>>>>" + ClassLayout.parseInstance(object).toPrintable());
                }
            }
        }).start();

        // 轻量锁进行cas操作后，仍然没拿到锁资源>>重量锁
        synchronized (object) {
            System.err.println("重量锁>>>>" + ClassLayout.parseInstance(object).toPrintable());
        }
    }

    /**
     * 轻量锁 00
     */
    private static void lightweightLock() {
        Object object = new Object();
        synchronized (object) {
            System.err.println("轻量锁>>>>" + ClassLayout.parseInstance(object).toPrintable());
        }
    }

    /**
     * 101 偏向锁
     */
    private static void deviationLock() {
        try {
            /**
             * 默认情况下，开启了偏向锁延迟，因为在jvm其中时，需要加载大量的.class文件到内存中，这个操作会涉及到synchronized的使用，为了避免
             * 出现偏向锁撤销操作，jvm启动初期又一个5s开启偏向锁操作
             *
             */
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        Object object = new Object();
        synchronized (object) {
            System.err.println("偏向锁>>>>" + ClassLayout.parseInstance(object).toPrintable());
        }
    }

    private static void nonLock() {
        Object object = new Object();
        // 无锁
        System.err.println("无锁>>>>" + ClassLayout.parseInstance(object).toPrintable());
    }
}
